package front

import (
	"fmt"
	"hft/Http/Models/dao"
	"hft/Http/Models/request/front"
	newFront "hft/Http/Models/request/front"
	utils "hft/Http/Utils"
	"hft/tools"
	"strconv"
	"strings"
	"time"

	"gorm.io/gorm"
)

type LouPan struct{}

func (l *LouPan) GetLouPanList(paginate *newFront.LouPanSearch, regionLinks []string, link string, names []string, roomTypes []int, tags []int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return db.Group("`hft_loupans`.`id`").Scopes(l.PriceSort(paginate.PriceSort, db)).Scopes(l.FirstWord(paginate.FirstWord, db)).Scopes(l.OpenTimeType(paginate.OpenTimeType, db)).Scopes(l.Preload(db)).Scopes(l.SellStatus(paginate.Status, db)).Scopes(l.SingleArea(paginate.AreaRange, db)).Scopes(l.CreateTime(paginate.CreateTimeSort, db)).Scopes(l.OpenTime(paginate.OpenTimeSort, db)).Scopes(l.Name(paginate.Name, db)).Scopes(l.PriceRange(paginate.Min, paginate.Max, db)).Scopes(l.Region(regionLinks, link, db)).Scopes(l.Feature(names, db)).Scopes(l.RoomType(roomTypes, db)).Scopes(l.Property(tags, db)).Scopes(l.TotalPrice(paginate.MinTotalPrice, paginate.MaxTotalPrice, db)).Scopes(l.PageOpera(paginate, db)).Scopes(l.Sort(db))
	}
}

func (l *LouPan) Name(name string, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if name == "" {
			return db
		} else {
			var name = "%%" + name + "%%"
			return db.Where("(name LIKE ? OR address LIKE ? OR belong_name LIKE ?)", name, name, name)
		}
	}
}

func (l *LouPan) PriceRange(min int, max int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if min < max {
			return db.Where("reference_price > ? AND reference_price < ?", min, max)
		} else if min > max {
			return db.Where("reference_price > ?", min)
		} else if min == 0 && max == 0 {
			return db
		} else {
			return db.Where("reference_price = ?", min)
		}
	}
}

func (l *LouPan) Region(regionLinks []string, link string, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if len(regionLinks) == 0 {
			return db.Where("region_link LIKE ?", link)
		} else if len(regionLinks) == 1 {
			return db.Where("region_link LIKE ?", fmt.Sprintf("%v%%", regionLinks[0]))
		} else {
			return db.Where("region_link IN ?", regionLinks)
		}
	}
}

func (l *LouPan) OpenTime(openTime int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if openTime == 1 {
			return db.Joins("SellLouPanInfo").Order("SellLouPanInfo.open_time desc")
		} else if openTime == 2 {
			return db.Joins("SellLouPanInfo").Order("SellLouPanInfo.open_time asc")
		} else {
			return db
		}
	}
}

func (l *LouPan) CreateTime(createTime int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if createTime == 1 {
			return db.Order("`hft_loupans`.`create_time` desc")
		} else if createTime == 2 {
			return db.Order("`hft_loupans`.`create_time` asc")
		} else {
			return db
		}
	}
}

func (l *LouPan) PriceSort(priceSort int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if priceSort == 1 {
			return db.Order("`hft_loupans`.`reference_price` desc")
		} else if priceSort == 2 {
			return db.Order("`hft_loupans`.`reference_price` asc")
		} else {
			return db
		}
	}
}

func (l *LouPan) Feature(names []string, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if (len(names) == 1 && names[0] == "") || len(names) == 0 {
			return db
		} else {
			return db.Joins("JOIN `hft_loupan_tese` ON `hft_loupan_tese`.`lou_pan_id` = `hft_loupans`.`id`").Where("`hft_loupan_tese`.`lou_pan_te_se_name`  IN ?", names)
		}
	}
}

func (l *LouPan) Sort(db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return db.Order("`hft_loupans`.`sort` desc")
	}
}

func (l *LouPan) RoomType(roomTypes []int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if len(roomTypes) == 0 {
			return db
		} else {
			return db.Joins("JOIN `hft_loupan_room_type` ON `hft_loupan_room_type`.`lou_pan_id` = `hft_loupans`.`id`").Where("`hft_loupan_room_type`.`room_type_id` IN ?", roomTypes)
		}
	}
}

func (l *LouPan) OpenTimeType(timeType int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		var milliSecond = utils.GetOpenTime(timeType)
		var nowTime = time.Now().UnixMilli()
		if milliSecond == 0 {
			return db
		} else if nowTime <= milliSecond {
			return db.Where("`SellLouPanInfo`.`open_time` >= ? AND `SellLouPanInfo`.`open_time` <= ?", nowTime, milliSecond)
		} else {
			return db.Where("`SellLouPanInfo`.`open_time` >= ? AND `SellLouPanInfo`.`open_time` <= ?", milliSecond, nowTime)
		}
	}
}

func (l *LouPan) Property(property []int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if len(property) == 0 {
			return db
		} else {
			return db.Joins("JOIN `hft_loupan_property` ON `hft_loupan_property`.`lou_pan_id` = `hft_loupans`.`id`").Where("`hft_loupan_property`.`property_status_code` IN ?", property)
		}
	}
}

func (l *LouPan) SellStatus(status int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if status == 0 {
			return db
		} else {
			return db.Where("status = ?", status)
		}
	}
}

func (l *LouPan) Preload(db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return db.Preload("Tags", func(db *gorm.DB) *gorm.DB {
			return db.Select("name,id")
		}).Preload("Disadvantage", func(db *gorm.DB) *gorm.DB {
			return db.Omit("region_link")
		}).Preload("RoomType", func(db *gorm.DB) *gorm.DB {
			return db.Select("id,name")
		}).Preload("SellLouPanInfo").Omit("region_link,first_word,years,furnish,isAudit").Preload("Properties", func(db *gorm.DB) *gorm.DB {
			return db.Omit("create_time,update_time,sort")
		}).Preload("TeSe", func(db *gorm.DB) *gorm.DB {
			return db.Select("id,name")
		})
	}
}

func (l *LouPan) Area(areaRange string, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	fmt.Println("范围", areaRange)
	return func(db *gorm.DB) *gorm.DB {

		var str = strings.Split(areaRange, "|")

		if len(str) == 0 {
			return db
		} else if len(str) == 1 {
			var str2 = strings.Split(str[0], "-")
			maxArea, _ := strconv.Atoi(str2[1])
			minArea, _ := strconv.Atoi(str2[0])
			if maxArea == 0 && minArea == 0 {
				return db
			} else if minArea >= maxArea {
				return db.Where("max_area >= ?", minArea)
			} else {
				return db.Where("(max_area >= ? AND min_area <= ?) OR (min_area <= ? AND max_area >= ?) OR (min_area <= ? AND max_area >= ?)", minArea, minArea, maxArea, maxArea, minArea, maxArea)
			}
		} else {
			return db
		}

	}
}

func (l *LouPan) SingleArea(areaRange string, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		fmt.Println("范围asdkaksdkasdkaksdkask1kasjdkas", areaRange)
		if areaRange == "" {
			return db
		}
		var str = strings.Split(areaRange, "|")
		var areaStr []string
		for _, v := range str {
			var str1 = strings.Split(v, "-")

			var maxArea, _ = strconv.Atoi(str1[1])
			var minArea, _ = strconv.Atoi(str1[0])
			var search string
			if maxArea < minArea {
				search = fmt.Sprintf("(max_area >= %v)", minArea)
			} else {
				search = fmt.Sprintf("((max_area >= %v AND min_area <= %v) OR (min_area <= %v AND max_area >= %v) OR (min_area <= %v AND max_area >= %v))", minArea, minArea, maxArea, maxArea, minArea, maxArea)
			}

			areaStr = append(areaStr, search)
		}
		newSearch := fmt.Sprintf("(%v)", strings.Join(areaStr, "OR"))

		return db.Where(newSearch)

	}
}

// 首字母
func (l *LouPan) FirstWord(firstWord string, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if firstWord == "" {
			return db
		} else {
			return db.Where("first_word = ?", firstWord)
		}
	}
}

func (l *LouPan) TotalPrice(minTotalPrice int, maxTotalPrice int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	fmt.Println(minTotalPrice, maxTotalPrice)
	return func(db *gorm.DB) *gorm.DB {
		if minTotalPrice == 0 && maxTotalPrice == 0 {
			return db
		} else if minTotalPrice <= maxTotalPrice {
			return db.Where("max_area * reference_price > ? AND min_area * reference_price < ?", minTotalPrice, maxTotalPrice)
		} else {
			return db.Where("max_area * reference_price < ?", maxTotalPrice)
		}
	}
}

func (l *LouPan) PageOpera(paginate *newFront.LouPanSearch, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if paginate.PageSize == 0 {
			return db
		} else {
			return db.Scopes(utils.Paginate(utils.Page(paginate.Page), db))
		}
	}
}

/* 户型一览 */
func (l *LouPan) RoomList(paginate *front.RoomSearch, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	fmt.Println(tools.JsonParse(paginate))
	return func(db *gorm.DB) *gorm.DB {
		return db.Where("lou_pan_id = ?", paginate.LouID).Scopes(l.RoomStatus(paginate.Status, db)).Scopes(l.RoomTypeSearch(paginate.RoomID, db)).Order("sort desc").Scopes(dao.Paginate(dao.Page(paginate.Page), db))
	}
}

// 户型销售状态
func (l *LouPan) RoomStatus(status int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if status == 0 {
			return db
		} else {
			return db.Where("status = ?", status)
		}
	}
}

// 户型
func (l *LouPan) RoomTypeSearch(roomID []int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if len(roomID) == 0 {
			return db
		} else {
			return db.Where("room_id in ?", roomID)
		}
	}
}

// 获取户型详情
func (l *LouPan) GetRoomInfo(roomID int, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return db.Scopes(l.SelectRoom(db)).Scopes(l.JoinRoom(db)).Where("hft_room.`id` = ?", roomID)
	}
}

func (l *LouPan) SelectRoom(db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return db.Select("hft_room.`lou_pan_id`,hft_room.`name`,hft_room.`status`,hft_room.`reference_price`,hft_room.`room_id`,hft_room.`forward`,hft_room.`area`,l.`name` as 'lou_name',hft_room.`room_pay_type`,hft_room.`first_pay`,s.`sell_phone`")
	}
}

// 联表
func (l *LouPan) JoinRoom(db *gorm.DB) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return db.Joins("LEFT JOIN hft_sell_lou_pan_info AS s on s.`lou_pan_id` = hft_room.`lou_pan_id`").Joins("LEFT JOIN hft_loupans AS l on l.id = hft_room.`lou_pan_id`")
	}
}

var LouPanDao = new(LouPan)
